/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package argtrust.tidal;

import argtrust.argsys.*;
import argtrust.measure.Measure;
import argtrust.measure.IMeasureOperators;
import argtrust.measure.LevelMeasure;
import argtrust.measure.LevelMeasureOperators;
import argtrust.trustnet.Agent;
import argtrust.trustnet.TrustNet;
import argtrust.trustnet.*;
import java.util.Map;
import java.util.Set;
import java.util.LinkedHashMap;

import argtrust.belief.BeliefBase;
import argtrust.belief.Belief;
import argtrust.logic.InferenceNode;
import argtrust.logic.FactInferenceNode;
import argtrust.logic.RuleInferenceNode;

import argtrust.belief.ITrustBeliefSemantics;
import argtrust.belief.IndirectBelief;
import argtrust.util.Pair;

/**
 *
 * @author Yuqing Tang
 */
public class TidalBeliefArgument //        implements IBeliefArgumentSemantics
{

    Map<Pair<Agent, Object>, Measure> mArgumentBeliefTable =
            new LinkedHashMap<Pair<Agent, Object>, Measure>();
    TrustNet mTrustnet;
    BeliefBase mBeliefBase;
    LevelMeasureOperators mOperators;
    double mTheta = 0;

    public TidalBeliefArgument(
            TrustNet trust_net,
            BeliefBase belief_base) {
        mTrustnet = trust_net;
        mBeliefBase = belief_base;
        mOperators = new LevelMeasureOperators();
    }

    public IMeasureOperators getOperators() {
        return mOperators;
    }

    LevelMeasure getLevelMeasure(Measure measure) {
        return (LevelMeasure) measure.getOpMeasure();
    }

    double levelMeasure(Measure measure) {
        if (measure.getOpMeasure() instanceof LevelMeasure) {
            return ((LevelMeasure) measure.getOpMeasure()).getLevel();
        } else {
            //TODO: throw exception
            System.err.println("TidalTrust is having trouble in getting trust level");
            if (measure != null) {
                System.err.println("Measure type: " + measure.getClass().getName());
            }
            return 0;
        }
    }

    public double trustLevel(Agent agent, Agent other) {
        return levelMeasure(trust(agent, other));

    }

    /**
     * Compute the trust in an inversed way.
     * @param agent
     * @param other
     * @return trust between agent and other.
     */
    Measure trust(Agent agent, Agent other) {
        Pair<Agent, Object> edge = new Pair<Agent, Object>(agent, other);
        Measure res = mArgumentBeliefTable.get(edge);
        if (res == null) {
            TrustNode trust_node = mTrustnet.getTrustNode(other);
            double numerator = 0;
            double denominator = 0;
            for (TrustLink trust_link : trust_node.getInvTrustLinkList()) {
                Trust tr = trust_link.getTrust();
                if (tr.getHead().equals(agent)) {

                    res = new LevelMeasure((LevelMeasure) tr.getMeasure());
                    mArgumentBeliefTable.put(edge, res);
                    return res;
                }
                double tr_level = levelMeasure(tr.getMeasure());
                if (tr_level >= mTheta) {
                    denominator += tr_level;
                    numerator += tr_level * levelMeasure(trust(agent, tr.getHead()));
                }
            }
            IndirectTrust ind_trust = new IndirectTrust();
            if (denominator != 0) {
                ind_trust.setMeasure(new LevelMeasure(numerator / denominator));
            } else {
                ind_trust.setMeasure(new LevelMeasure(0));

            }
            mArgumentBeliefTable.put(edge, ind_trust);
            res = ind_trust;
        }
        return res;
    }

//Measure believe(Agent agent, Argument argument)
//           {
//       return null;
//
//
//}
//    Measure believe_(Agent agent, InferenceNode inf_node) {
//
//        Set<Belief> belief_set = null;
//        double numerator = 0;
//        double denominator = 0;
//        if (inf_node instanceof FactInferenceNode) {
//            FactInferenceNode fact_node = (FactInferenceNode) inf_node;
//            belief_set = mBeliefBase.getBeliefSet(fact_node.getFactIterator().get());
//        } else {
//            RuleInferenceNode rule_node = (RuleInferenceNode) inf_node;
//            belief_set =
//                    mBeliefBase.getBeliefSet(rule_node.getRuleIterator().get());
//        }
//        if (belief_set != null) {
//            for (Belief belief : belief_set) {
//                if (belief.getOwner().equals(agent)) {
//                    double bl_level = this.levelMeasure(belief.getMeasure());
//                    if (bl_level >= mTheta) {
//                        //Self belief: assume the weight is 1.
//                        //TODO: will decide whether to return here.
//                        denominator += 1; //bl_level;
//                        numerator += bl_level;// * levelMeasure(trust(agent, tr.getHead()));
//                    }
//                } else {
//                    double bl_level = levelMeasure(belief.getMeasure());
//                    if (bl_level >= mTheta) {
//                        denominator += bl_level;
//                        numerator += bl_level * levelMeasure(trust(agent, belief.getOwner()));
//                    }
//                }
//            }
//
//        }
//
//        if (inf_node instanceof RuleInferenceNode) {
//            for (InferenceNode node : ((RuleInferenceNode) inf_node).getChildrenList()) {
//                double bl_level = levelMeasure(believe_(agent, node));
//                if (bl_level >= mTheta) {
//                    denominator += bl_level;
//                    numerator += bl_level * levelMeasure(trust(agent, belief.getOwner()));
//                }
//            }
//        }
//        return null;
//    }

    public Measure believe(Agent agent, Argument argument) {
        return null;
//        Pair<Agent, Object> key = new Pair<Agent, Object>(agent, argument);
//        Measure res = mArgumentBeliefTable.get(key);
//
//
//
//
//
//
//        if (res == null) {
//            res = new IndirectBelief(
//                    believe_(agent, argument.getEndInferenceNode()));
//            mArgumentBeliefTable.put(key, res);
//
//
//
//
//
//
//        }
//
//        return res;




    }
//    public boolean isEffective(Agent agent, Defeat defeat) {
//        return !(believe(agent, defeat.getDefeatee()).getLevel()
//                > believe(agent, defeat.getDefeater()).getLevel());
//    }
}
